﻿using System;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using Package;
using ATMConst;

namespace ATMCableCloud
{
	class MainTCPServer : BasicTcpServer, ITCPInputOutput
	{
		protected override void peerDisconnectionHandler(Socket socket)
		{
		}
		void helloPackageHandling(	Package.Package package,
									IAsyncResult ar,
									Socket handler)
		{
			if (package.code != Const.Code.HELLO)
			{
				sendPackage(new InvalidMessagePackage((int)package.code),
							handler);
			}
			else
			{
				var hpackage = package as HelloPackage;
				AtmNode node;
				if (ConnectedAtmNodes.getInstance().find(hpackage.name,out node))
					sendPackage(new NameErrorPackage(hpackage.name),
								handler);
				else
				{
					try
					{
						var portNumber = ConnectedAtmNodes.getInstance().getPort();
						if (hpackage.type == HelloPackage.NodeType.UNI)
							ConnectedAtmNodes.getInstance().addNode(new AtmUserNode(
								(handler.RemoteEndPoint as IPEndPoint).Address,
								portNumber,
								hpackage.name));
						else
							ConnectedAtmNodes.getInstance().addNode(new AtmNetworkNode(
								(handler.RemoteEndPoint as IPEndPoint).Address,
								portNumber,
								hpackage.name));
							/*
							* now we have got a opened socket for this Node
							*/
						sendPackage(new HelloOkPackage(portNumber),
									handler);
					}
					catch (Exception e)
					{
						Console.WriteLine(e);
						sendPackage(new UnknownErrorPackage("Creating Node error"),
									handler);
					}
				}
			}
		}
		MainTCPServer(	IPAddress address, 
						int tcpPort) 
			:base(	address, 
					tcpPort,
					Const.MAX_PEERS_WAITING)
		{
			mainTcpPackageHandler = helloPackageHandling;
		}
		public static MainTCPServer getInstance()
		{
			if (rInstance_ == null)
			{
				mutex_.WaitOne();
				if (rInstance_ == null)
				{
					rInstance_ = new MainTCPServer(IPAddress.Any ,Const.DEFAULT_PORT_NUMBER);
				}
				mutex_.ReleaseMutex();
			}
			return rInstance_;
		}
		static MainTCPServer rInstance_ = null;
		static Mutex mutex_ = new Mutex();
	}
}